package com.varian.auth.authentication;

import com.varian.auth.authentication.handler.VarianAuthenticationFailureHandler;
import com.varian.auth.authentication.password.OAuth2ResourceOwnerPasswordAuthenticationConverter;
import com.varian.auth.authentication.password.OAuth2ResourceOwnerPasswordAuthenticationProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.core.OAuth2Token;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationEndpointConfigurer;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2TokenEndpointConfigurer;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
import org.springframework.security.oauth2.server.authorization.web.authentication.OAuth2AccessTokenResponseAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

/**
 * @author ben
 * @since 2024/6/24
 */
@RequiredArgsConstructor
public class VarianAuthentication {

    private final AuthenticationSuccessHandler authenticationSuccessHandler;
    private final AuthenticationFailureHandler authenticationFailureHandler;

    public VarianAuthentication() {
        this.authenticationSuccessHandler = new OAuth2AccessTokenResponseAuthenticationSuccessHandler();
        this.authenticationFailureHandler = new VarianAuthenticationFailureHandler();
    }

    public void tokenEndpoint(
            OAuth2TokenEndpointConfigurer configurer,
            UserDetailsService userDetailsService,
            OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator,
            OAuth2AuthorizationService authorizationService,
            PasswordEncoder passwordEncoder
    ) {
        OAuth2ResourceOwnerPasswordAuthenticationProvider authenticationProvider =
                new OAuth2ResourceOwnerPasswordAuthenticationProvider(userDetailsService, tokenGenerator, authorizationService, passwordEncoder);
        configurer
                .accessTokenRequestConverter(new OAuth2ResourceOwnerPasswordAuthenticationConverter())
                .authenticationProvider(authenticationProvider)
                .accessTokenResponseHandler(authenticationSuccessHandler)
                .errorResponseHandler(authenticationFailureHandler);
    }


    public void authorizationEndpoint(OAuth2AuthorizationEndpointConfigurer configurer) {
        configurer.errorResponseHandler(authenticationFailureHandler);
    }
}
